package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.article.mapper.ApArticleConfigMapper;
import com.heima.article.mapper.ApArticleContentMapper;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.ApArticleService;
import com.heima.article.service.ArticleFreemarkerService;
import com.heima.common.constants.ArticleConstants;
import com.heima.common.constants.BehaviorConstants;
import com.heima.common.constants.ScheduleConstants;
import com.heima.common.redis.CacheService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.article.dtos.ArticleHomeDto;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.pojos.ApArticleConfig;
import com.heima.model.article.pojos.ApArticleContent;
import com.heima.model.behavior.dtos.*;
import com.heima.model.behavior.vos.ArticleBehaviorVo;
import com.heima.model.comment.dtos.CommentArticleDto;
import com.heima.model.comment.dtos.CommentOperationDto;
import com.heima.model.comment.vos.ArticleCommentVo;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.model.wemedia.dtos.StatisticsPageDto;
import com.heima.utils.common.AppThreadLocalUtil;
import com.heima.utils.common.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author 陈辉
 * @data 2023 15:41
 */
@Service
public class ApArticleServiceImpl extends ServiceImpl<ApArticleMapper, ApArticle> implements ApArticleService {
    @Autowired
    private ApArticleMapper apArticleMapper;
    @Autowired
    private ApArticleContentMapper apArticleContentMapper;
    @Autowired
    private ApArticleConfigMapper apArticleConfigMapper;
    @Autowired
    private ArticleFreemarkerService articleFreemarkerService;
    @Autowired
    private CacheService cacheService;
    /**
     * app文章首页加载/加载更多/加载更新
     * @param dto
     * @param type
     * @return
     */
    @Override
    public ResponseResult load(ArticleHomeDto dto, Short type) {
        //1. 参数校验
        if (dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //2. 数据处理
        //2.1 先处理分页： 最大一页50
        if (dto.getSize() == null) {
            dto.setSize(10);
        } else {
            dto.setSize(Math.min(dto.getSize(), 50));
        }

        //2.2 再处理频道ID
        if (StringUtils.isBlank(dto.getTag())) {
            dto.setTag(ArticleConstants.DEFAULT_TAG);   //默认频道
        }
        //2.3 最后处理时间
        if (dto.getMinBehotTime() == null) {
            dto.setMinBehotTime(new Date());
        }
        if (dto.getMaxBehotTime() == null) {
            dto.setMaxBehotTime(new Date());
        }


        //3. 业务操作
        return ResponseResult.okResult(apArticleMapper.loadArticleList(dto,type));
    }


    /**
     * 保存或修改app文章信息
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveOrUpdateArticle(ArticleDto dto) {
        //参数校验
        if (dto == null || StringUtils.isBlank(dto.getContent())){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        ApArticle article = new ApArticle();
        BeanUtils.copyProperties(dto,article);

        //1. 根据文章id来区分：新增/修改
        if (dto.getId() == null){
            //第一次数据同步：新增处理: ap_article, ap_article_config,ap_article_content
            save(article);

            //处理文章配置信息
            ApArticleConfig config = new ApArticleConfig(article.getId());
            apArticleConfigMapper.insert(config);

            //处理文章内容
            ApArticleContent content = new ApArticleContent();
            content.setContent(dto.getContent());
            content.setArticleId(article.getId());
            apArticleContentMapper.insert(content);

        }else{
            //不是第一次数据同步：修改处理 : 只能改文章信息和文章内容信息，不能改文章配置信息!
            updateById(article);

            //修改文章内容
            ApArticleContent apArticleContent = apArticleContentMapper.selectOne(Wrappers.<ApArticleContent>lambdaQuery().eq(ApArticleContent::getArticleId, dto.getId()));
            apArticleContent.setContent(dto.getContent());
            apArticleContentMapper.updateById(apArticleContent);
        }

        //生成文章详情页，回填: static_url
        articleFreemarkerService.buildArticleToMinIO(article,dto.getContent());

        return ResponseResult.okResult(article.getId());
    }

    /**
     * 根据id获取作者名称
     *
     * @param id
     * @return
     */
    @Override
    public ResponseResult getNameById(Integer id) {
        ApArticle apArticle = apArticleMapper.selectById(id);
        String authorName = apArticle.getAuthorName();
        return ResponseResult.okResult(authorName);
    }

    /**
     * 查询文章和评论
     * @param dto
     * @return
     */
    @Override
    public ResponseResult findNewsComments(CommentArticleDto dto) {
        //获取文章
        List<ApArticle> apArticles = apArticleMapper.selectList(Wrappers.<ApArticle>lambdaQuery().orderByDesc(ApArticle::getCreatedTime)
                .eq(ApArticle::getAuthorId,dto.getWmUserId()));
        //前端返回的页面
        List<ArticleCommentVo> list=new ArrayList<>();
        for (ApArticle apArticle : apArticles) {
            ArticleCommentVo articleCommentVo = new ArticleCommentVo();
            String title = apArticle.getTitle();
            ApArticleConfig apArticleConfig = apArticleConfigMapper.
                    selectOne(Wrappers.<ApArticleConfig>lambdaQuery().eq(ApArticleConfig::getArticleId, apArticle.getId()));
            Boolean isComment = apArticleConfig.getIsComment();
            Integer comments = apArticle.getComment();
            //进行赋值
           articleCommentVo.setTitle(title);
           articleCommentVo.setComment(isComment);
           articleCommentVo.setComments(comments);
           articleCommentVo.setId(apArticle.getId().toString());
           list.add(articleCommentVo);
        }
        LambdaQueryWrapper<ApArticle> wrapper=new LambdaQueryWrapper();

        wrapper.orderByDesc(ApArticle::getCreatedTime);
        wrapper.between(ApArticle::getPublishTime,dto.getBeginDate(),dto.getEndDate());
        IPage ipage = new Page(dto.getPage(), dto.getSize());
       page(ipage, wrapper);

        PageResponseResult pageResponseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int) ipage.getTotal());
        pageResponseResult.setData(list);
        return pageResponseResult;
    }

    /**
     * 加载文章行为-数据回显
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult article_behavior(ArticleInfoDto dto) {
        //参数校验
        ApUser user = AppThreadLocalUtil.getUser();

        if (dto==null||dto.getArticleId()==null||dto.getAuthorId()==null
        ||user==null||user.getId()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //数据处理
        ArticleBehaviorVo vo = new ArticleBehaviorVo();

        String isLikeKey = BehaviorConstants.LIKES + user.getId()+"_"+dto.getArticleId();
        String isUnlikeKey = BehaviorConstants.UN_LIKE + user.getId()+"_"+dto.getArticleId();
        String isFollowKey = BehaviorConstants.FOLLOW +"*"+/*dto.getArticleId()*/+dto.getAuthorId();
        String iscollectionKey = BehaviorConstants.COLLECTION + user.getId()+"_"+dto.getArticleId();

        //装填like
        Set<String> likeKeys = cacheService.scan(isLikeKey);
        /*LikesOrUnlike likesOrUnlike = JSON.parseObject(cacheService.get(isLikeKey), LikesOrUnlike.class);*/
        if (likeKeys.size()>0) {
            vo.setIslike(true);
        } else {
            vo.setIslike(false);
        }


        //装填isunlike

        Set<String> isUnlikeKeys = cacheService.scan(isUnlikeKey);
        /*UnLikesBehaviorDto unLikesBehaviorDto = JSON.parseObject(isUnlikeDto, UnLikesBehaviorDto.class);*/
            if (isUnlikeKeys.size()>0){
                vo.setIsunlike(true);
            }else {
                vo.setIsunlike(false);
            }


        //装填isfollow
        Set<String> followKeys = cacheService.scan(isFollowKey);
        /*FollowBehaviorDto followBehaviorDto = JSON.parseObject(isFollowDto, FollowBehaviorDto.class);*/
            if (followKeys.size()>0){
                vo.setIsfollow(true);
            }else {
                vo.setIsfollow(false);
            }


        //装填iscollection

        Set<String> iscollections = cacheService.scan(iscollectionKey);
        /*CollectionBehaviorDto collectionBehaviorDto = JSON.parseObject(iscollectionDto, CollectionBehaviorDto.class);*/
            if (iscollections.size()>0){
                vo.setIscollection(true);
            }else {
                vo.setIscollection(false);
            }


        return ResponseResult.okResult(vo);
    }

    /**
     * 修改文章评论状态
     * @param dto
     * @return
     */
    @Override
    public ResponseResult updateArticleStatus(CommentOperationDto dto) {
       Long articleId = dto.getArticleId();
        Integer operation = dto.getOperation();
        boolean isComment=true;
        if (operation==0){
            isComment= false;
        }
        //根据文章id查询到文章配置
        ApArticleConfig apArticleConfig = apArticleConfigMapper.selectOne(Wrappers.<ApArticleConfig>lambdaQuery()
                .eq(ApArticleConfig::getArticleId,articleId) );
        //修改文章配置表属性 更改状态
        apArticleConfig.setIsComment(isComment);
        apArticleConfigMapper.updateById(apArticleConfig);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }


    /**
     * 图文统计
     * @param wmUserId
     * @param beginDate
     * @param endDate
     * @return
     */
    @Override
    public ResponseResult statisticsNum(Integer wmUserId, Date beginDate, Date endDate) {
        Map map = apArticleMapper.selectstatisticsNum(wmUserId, beginDate, endDate);
        return ResponseResult.okResult(map);
    }

    /**
     * 文章统计-分页统计
     * @param dto
     * @return
     */
    @Override
    public ResponseResult newPage(StatisticsPageDto dto) {
        //类型转换
        Date beginDate = DateUtils.stringToDate(dto.getBeginDate());
        Date endDate = DateUtils.stringToDate(dto.getEndDate());
        //检查参数
        dto.checkParam();
        //分页查询
        IPage page = new Page(dto.getPage(), dto.getSize());
        LambdaQueryWrapper<ApArticle> lambdaQueryWrapper = Wrappers.<ApArticle>lambdaQuery()
                .select(ApArticle::getId,ApArticle::getTitle,ApArticle::getLikes,ApArticle::getCollection,ApArticle::getComment,ApArticle::getViews)
                .eq(ApArticle::getAuthorId, dto.getId())
                .between(ApArticle::getPublishTime,beginDate, endDate);

        lambdaQueryWrapper.orderByDesc(ApArticle::getPublishTime);

        page = page(page,lambdaQueryWrapper);


        PageResponseResult responseResult = new PageResponseResult(dto.getPage(),dto.getSize(),(int)page.getTotal());
        responseResult.setData(page.getRecords());

        return responseResult;
    }

    //增加评论数
    @Override
    public void AddComment(Long articleId) {
        ApArticle apArticle = getById(articleId);
        if(apArticle.getComment()==null){
            apArticle.setComment(0);
        }
        update(Wrappers.<ApArticle>lambdaUpdate().set(ApArticle::getComment, apArticle.getComment()+1).eq(ApArticle::getId,articleId));
    }

    //减少评论数
    @Override
    public void ReduceComment(Long articleId) {
        ApArticle apArticle = getById(articleId);
        if(apArticle.getComment()==null){
            apArticle.setComment(0);
        }
        if(apArticle.getComment()>=1) {
        }
        update(Wrappers.<ApArticle>lambdaUpdate().set(ApArticle::getComment, apArticle.getComment()-1).eq(ApArticle::getId,articleId));
    }
}
